package fr.gadcparis.envieparisienne.model;

import java.io.Serializable;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.json.JSONException;
import org.json.JSONObject;

import com.google.android.maps.GeoPoint;

import android.location.Location;
import android.util.Log;

public class Hit implements Serializable {
	
	private static final long serialVersionUID = 1L;
	
	transient private Location location;
	private double latitude;
	private double longitude;
	private Map<String, String> metas;
	
	protected Hit() {
		this.location = null;
		this.metas = new HashMap<String, String>();
	}
	
	public static Hit fromJSON(JSONObject jsonHit) {
		Hit hit = new Hit();
		JSONObject data = jsonHit;
		Location location = null;
		if (jsonHit.has("data")) {
			try {
				data = jsonHit.getJSONObject("data");
				hit.latitude = jsonHit.getDouble("lat");
				hit.longitude = jsonHit.getDouble("long");
				location = new Location("hit"); 
				location.setLatitude(hit.latitude);
				location.setLongitude(hit.longitude);
				hit.setLocation(location);
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
		hit.addMetas(data);
		return hit;
	}
	
	@SuppressWarnings("unchecked")
	private void addMetas(JSONObject data) {
		
		for (Iterator<String> keys = data.keys(); keys.hasNext() ; ) {
			String key = keys.next();
			if (key.equals("other_tags")) {
				try {
					JSONObject subData = new JSONObject(data.getString(key));
					addMetas(subData);
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			else {
				try {
					String value = data.getString(key);
					addMeta(key, value);
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

	protected void addMeta(String key, String value) {
		this.metas.put(key, value);
		
	}

	protected void setLocation(Location location) {
		this.location = location;
	}
	
	public Location getLocation() {
		if (this.location == null) {
			location = new Location(this.getAddress()); 
			location.setLatitude(latitude);
			location.setLongitude(longitude);
		}
		return this.location;
	}
	
	public GeoPoint getGeoPoint() {
		return new GeoPoint((int)(location.getLatitude()*1000000),(int)(location.getLongitude()*1000000));
	}
	
	public String getMeta(String key, String defaultValue) {
		if (metas.containsKey(key)) {
			return metas.get(key);
		}
		return defaultValue;
		
	}

	public String getName() {
		String name =  getMeta("name", "None");
		if (name.equals("None")) {
			name = getMeta("Libelle", "None");
			if (name.equals("None")) {
				name = getCategoryName();
			}
		}
		return name;
	}
	
	public String getAddress() {
		String address = getMeta("Adresse complète", null);
		if (address == null) {
			address = getMeta("address", null);
			if (address == null) {
				address = getMeta("ADRESSE", "");
			}
		}
		return address;
	}
	
	public int getCategory() {
		String dataset =  getMeta("datasetid", "");
		String amenity =  getMeta("amenity", "");
		if (dataset.equals("openstreetmapplaceitaliefeb2012")) {
			if (amenity.equals("restaurant") || amenity.equals("fast_food")) {
				return OpenDataClient.HUNGER_CLIENT;
			}
			else if (amenity.equals("cafe")) {
				return OpenDataClient.THIRSTY_CLIENT;
			}
		}
		else if (dataset.equals("mobiliereaupotableparis2011")) {
			return OpenDataClient.THIRSTY_CLIENT;
		}
		else if (dataset.equals("sanisettesparis2011")) {
			return OpenDataClient.PEE_CLIENT;
		}
		else if (dataset.equals("distributeurspreservatifsmasculinsparis2012")) {
			return OpenDataClient.SEX_CLIENT;
		}
		return OpenDataClient.ALL_CLIENT;
	}
	
	public String getCategoryName() {
		switch (getCategory()) {
		case OpenDataClient.THIRSTY_CLIENT:
			if ( getMeta("amenity", "").equals("cafe")) {
				return "Bar/Café";
			}
			else {
				return "Source d'eau";
			}
			
		case OpenDataClient.HUNGER_CLIENT:
			if ( getMeta("amenity", "").equals("fast_food")) {
				return "Fast food";
			}
			else {
				return "Restaurant";
			}
			
		case OpenDataClient.PEE_CLIENT:
			return "Toilettes";
			
		case OpenDataClient.SEX_CLIENT:
			return "Distributeur de preservatifs";
		}
		return "sans nom";
	}
	
	public String getType() {
		return getMeta("amenity", null);
	}
	
	public String getCuisine() {
		String cuisine = getMeta("cuisine", null);
		if (cuisine != null) {
			if (cuisine.contains("chinese")) {
				return "Chinois";
			}
			else if (cuisine.contains("vietnamese")) {
				return "Vietnamien";
			}
			else if (cuisine.contains("couscous")) {
				return "Couscous";
			}
			else if (cuisine.contains("french") || cuisine.contains("Cuisine traditionnelle")) {
				return "Français";
			}
			else if (cuisine.contains("japanese")) {
				return "Japonais";
			}
			else if (cuisine.contains("asian")) {
				return "Asiatique";
			}
			else if (cuisine.contains("italian")) {
				return "Italian";
			}
			else if (cuisine.contains("pizza")) {
				return "Pizza";
			}
			else if (cuisine.contains("regional")) {
				return "Regional";
			}
			else if (cuisine.contains("thai")) {
				return "Thailandais";
			}
			else if (cuisine.contains("burger")) {
				return "Fast-Food";
			}
		}
		return cuisine;
	}

	@Override
	public String toString() {
		return "Hit [location=" + location + ", metas=" + metas + "]";
	}
	
	private void writeObject(ObjectOutputStream out) throws IOException {
		out.defaultWriteObject();
	}

	private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
		in.defaultReadObject();
	}
	
	public String getDatasetId() {
		return getMeta("datasetid", "unknown");
	}
	
	public int getId() {
		Log.i("TOTO", "recordId" + getMeta("recordid", "-1"));
		return Integer.parseInt(getMeta("recordid", "-1"));
	}

}
